﻿//-----------------------------------------------------------------------
// <copyright file="StringExtensions.cs" company="CodePlex">
//     Copyright (c) Doug Holland, CodePlex. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace CodePlex.Diagnostics.Silverlight
{
    using System;

    using System.Collections;
    using System.Collections.Generic;

    using System.Reflection;

    using System.Security;
    using System.Security.Principal;

    using System.Threading;

    using System.Xml;
    using System.Xml.Linq;
    
    using CodePlex.Diagnostics.Silverlight.Contracts;
    
    /// <summary>
    /// Provides extension methods for the <see cref="T:System.String"/> class to enable the writing of log entries using the CodePlex.Diagnostics framework.
    /// </summary>
    public static class StringExtensions
    {
        #region public static Guid Log(this string entry, LoggingPriority priority, LoggingType type)

        /// <summary>
        /// Writes the <see cref="T:System.String"/> using the configured logging provider.
        /// </summary>
        /// <param name="entry">The <see cref="T:System.String"/> to be logged.</param>
        /// <param name="priority">The <see cref="T:CodePlex.Diagnostics.LoggingPriority"/> of the log entry.</param>
        /// <param name="type">The <see cref="T:CodePlex.Diagnostics.LoggingType"/> of the log entry.</param>
        /// <returns>A <see cref="T:System.Guid"/> representing the unique publication identifier for the log entry.</returns>
        public static Guid Log(this string entry, LoggingPriority priority, LoggingType type)
        {
            IIdentity identity = null;

            return entry.Log(priority, type, identity);
        }

        #endregion

        #region public static Guid Log(this string entry, LoggingPriority priority, LoggingType type, IIdentity identity)

        /// <summary>
        /// Writes the <see cref="T:System.String"/> using the configured logging provider.
        /// </summary>
        /// <param name="entry">The <see cref="T:System.String"/> to be logged.</param>
        /// <param name="priority">The <see cref="T:CodePlex.Diagnostics.LoggingPriority"/> of the log entry.</param>
        /// <param name="type">The <see cref="T:CodePlex.Diagnostics.LoggingType"/> of the log entry.</param>
        /// <param name="identity">The <see cref="T:System.Security.Principal.IIdentity"/> to associate with the log entry.</param>
        /// <returns>A <see cref="T:System.Guid"/> representing the unique publication identifier for the log entry.</returns>
        public static Guid Log(this string entry, LoggingPriority priority, LoggingType type, IIdentity identity)
        {
            return entry.Log(priority, type, null, identity);
        }

        #endregion

        #region public static Guid Log(this string entry, LoggingPriority priority, LoggingType type, Dictionary<string, string> dictionary)

        /// <summary>
        /// Writes the <see cref="T:System.String"/> using the configured logging provider.
        /// </summary>
        /// <param name="entry">The <see cref="T:System.String"/> to be logged.</param>
        /// <param name="priority">The <see cref="T:CodePlex.Diagnostics.LoggingPriority"/> of the log entry.</param>
        /// <param name="type">The <see cref="T:CodePlex.Diagnostics.LoggingType"/> of the log entry.</param>
        /// <param name="dictionary">A <see cref="T:System.Collections.Generic.Dictionary`2"/> containing name value pairs associated with this log entry.</param>
        /// <returns>A <see cref="T:System.Guid"/> representing the unique publication identifier for the log entry.</returns>
        public static Guid Log(this string entry, LoggingPriority priority, LoggingType type, Dictionary<string, string> dictionary)
        {
            return entry.Log(priority, type, dictionary, null);
        }

        #endregion

        #region public static Guid Log(this string entry, LoggingPriority priority, LoggingType type, Dictionary<string, string> dictionary, IIdentity identity)

        /// <summary>
        /// Writes the <see cref="T:System.String"/> using the configured logging provider.
        /// </summary>
        /// <param name="entry">The <see cref="T:System.String"/> to be logged.</param>
        /// <param name="priority">The <see cref="T:CodePlex.Diagnostics.LoggingPriority"/> of the log entry.</param>
        /// <param name="type">The <see cref="T:CodePlex.Diagnostics.LoggingType"/> of the log entry.</param>
        /// <param name="dictionary">A <see cref="T:System.Collections.Generic.Dictionary`2"/> containing name value pairs associated with this log entry.</param>
        /// <param name="identity">The <see cref="T:System.Security.Principal.IIdentity"/> to associate with the log entry.</param>
        /// <returns>A <see cref="T:System.Guid"/> representing the unique publication identifier for the log entry.</returns>
        public static Guid Log(this string entry, LoggingPriority priority, LoggingType type, Dictionary<string, string> dictionary, IIdentity identity)
        {
            return entry.Log(priority, type, dictionary, null, identity);
        }

        #endregion

        #region public static Guid Log(this string entry, LoggingPriority priority, LoggingType type, Dictionary<string, string> dictionary, XElement element, IIdentity identity)

        /// <summary>
        /// Writes the <see cref="T:System.String"/> using the configured logging provider.
        /// </summary>
        /// <param name="entry">The <see cref="T:System.String"/> to be logged.</param>
        /// <param name="priority">The <see cref="T:CodePlex.Diagnostics.LoggingPriority"/> of the log entry.</param>
        /// <param name="type">The <see cref="T:CodePlex.Diagnostics.LoggingType"/> of the log entry.</param>
        /// <param name="dictionary">A <see cref="T:System.Collections.Generic.Dictionary`2"/> containing name value pairs associated with this log entry.</param>
        /// <param name="element">A <see cref="T:System.Xml.Linq.XElement"/> representing an xml element to be associated with this log entry.</param>
        /// <param name="identity">The <see cref="T:System.Security.Principal.IIdentity"/> to associate with the log entry.</param>
        /// <returns>A <see cref="T:System.Guid"/> representing the unique publication identifier for the log entry.</returns>
        public static Guid Log(this string entry, LoggingPriority priority, LoggingType type, Dictionary<string, string> dictionary, XElement element, IIdentity identity)
        {
            // establish an identity data contract based upon the supplied identity object.
            IIdentityDataContract identityDataContract = new IIdentityDataContract(identity);

            // establish the log entry data contract.
            LogEntryDataContract logEntryDataContract = new LogEntryDataContract(entry, priority, type);

            // establish the application domain data contract based upon the current domain.
            logEntryDataContract.AppDomain = new AppDomainDataContract();

            Assembly assembly = Assembly.GetCallingAssembly();

            // establish the assembly data contract based upon the calling assembly, that is the assembly containing the method calling this method.
            logEntryDataContract.Assembly = new AssemblyDataContract(assembly);

            // establish the machine data contract.
            logEntryDataContract.Machine = new MachineDataContract();

            // establish the process data contract based upon the current process.
            logEntryDataContract.Process = new ProcessDataContract();

            // establish the thread data contract based upon the current thread.
            logEntryDataContract.Thread = new ThreadDataContract(Thread.CurrentThread);

            // establish a proxy to the diagnostics service.
            DiagnosticsServiceClient client = new DiagnosticsServiceClient();

            Guid publicationId = Guid.Empty;

            client.LogCompleted += delegate(object sender, LogCompletedEventArgs e)
            {
                publicationId = e.PublicationId;
            };

            // publish the exception using the diagnostics service, returning the publication identifier.
            client.LogAsync(logEntryDataContract, dictionary, element, identityDataContract);

            return publicationId;
        }

        #endregion
    }
}